package unicamp.redes.rmi;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.rmi.RemoteException;

public class DacImpl implements Dac {

	private String DB = "db.txt";
	private String USERS = "users.txt";
	private Integer PROFESSOR_AUTH = Integer.valueOf(1);
	private Integer STUDENT_AUTH = Integer.valueOf(2);

	private BufferedReader dbFile;

	@Override
	public String start(Integer option, String code, String user, String pass,
			String commentary) throws RemoteException {
		
		//TODO inicio da medida de tempo (processamento)
		long start = System.nanoTime();
		String result = "";
		FileReader fr;
		try {
			fr = new FileReader(DB);
			dbFile = new BufferedReader(fr);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		switch (option) {
		case 1:
			result = getCodeTitleAllDisciplines();
			break;
		case 2:
			result = getAllDisciplines();
			break;
		case 3:
			result = getProgramByCode(code);
			break;
		case 4:
			result = getCompleteDisciplineByCode(code);
			break;
		case 5:
			result = getCommentaryByCode(code);
			break;
		case 6:
			result = changeCommentaryByCode(code, commentary, user, pass);
			break;
		default:
			result = "ERRO";
			break;
		}
		long end = System.nanoTime() - start;
		saveTimes(end);
		// TODO Termino da medida de tempo (processamento)
		return result;

	}

	private String getCodeTitleAllDisciplines() {
		String string = null;
		StringBuilder result = new StringBuilder();
		Discipline d = new Discipline();
		result.append("CODIGO -- DISCIPLINA");
		result.append(System.getProperty("line.separator"));

		try {
			while ((string = dbFile.readLine()) != null) {
				d.createDisciplineFromString(string);
				if (d.getRemoved().compareTo(Boolean.TRUE) == 0) {
					// Caso a disciplina esteja removida, pega a proxima
					continue;
				}
				result.append(d.getCode());
				result.append(" -- ");
				result.append(d.getTitle());
				result.append(System.getProperty("line.separator"));
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return result.toString();
	}

	private String getAllDisciplines() {
		String string = null;
		StringBuilder result = new StringBuilder();
		Discipline d = new Discipline();

		try {
			while ((string = dbFile.readLine()) != null) {
				d.createDisciplineFromString(string);
				if (d.getRemoved().compareTo(Boolean.TRUE) == 0) {
					// Caso a disciplina esteja removida, pega a proxima
					continue;
				}
				result.append(Discipline.CODE_NAME);
				result.append(": ");
				result.append(d.getCode());
				result.append(System.getProperty("line.separator"));
				result.append(Discipline.TITLE_NAME);
				result.append(": ");
				result.append(d.getTitle());
				result.append(System.getProperty("line.separator"));
				result.append(Discipline.PROGRAM_NAME);
				result.append(": ");
				result.append(d.getProgram());
				result.append(System.getProperty("line.separator"));
				result.append(Discipline.ROOM_NAME);
				result.append(": ");
				result.append(d.getRoom());
				result.append(System.getProperty("line.separator"));
				result.append(Discipline.TIME_NAME);
				result.append(": ");
				result.append(d.getTime());
				result.append(System.getProperty("line.separator"));
				result.append(Discipline.COMMENTARY_NAME);
				result.append(": ");
				result.append(d.getCommentary());
				result.append(System.getProperty("line.separator"));
				result.append(System.getProperty("line.separator"));
				result.append("---------------------------------------------------------");
				result.append(System.getProperty("line.separator"));
			}
		} catch (IOException e) {
			e.printStackTrace();
		}

		return result.toString();
	}

	private Discipline getDisciplineByCode(String code) {
		String string;
		Discipline d = new Discipline();
		Discipline result = null;
		try {
			while ((string = dbFile.readLine()) != null) {
				d.createDisciplineFromString(string);
				if (d.getCode().compareTo(code) == 0
						&& d.getRemoved().compareTo(Boolean.FALSE) == 0) {
					result = d;
					break;
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return result;
	}

	private String getProgramByCode(String code) {
		StringBuilder result = new StringBuilder();
		Discipline d = new Discipline();
		result.append(System.getProperty("line.separator"));

		d = getDisciplineByCode(code);
		if (d == null) {
			return "Disciplina n�o encontrada";
		}
		result.append(Discipline.PROGRAM_NAME);
		result.append(": ");
		result.append(d.getProgram());
		result.append(System.getProperty("line.separator"));

		return result.toString();
	}

	private String getCompleteDisciplineByCode(String code) {
		String string = null;
		StringBuilder result = new StringBuilder();
		Discipline d = null;
		
		d = getDisciplineByCode(code);
		if (d == null) {
			return "Disciplina n�o encontrada";
		}

		result.append(Discipline.CODE_NAME);
		result.append(": ");
		result.append(d.getCode());
		result.append(System.getProperty("line.separator"));
		result.append(Discipline.TITLE_NAME);
		result.append(": ");
		result.append(d.getTitle());
		result.append(System.getProperty("line.separator"));
		result.append(Discipline.PROGRAM_NAME);
		result.append(": ");
		result.append(d.getProgram());
		result.append(System.getProperty("line.separator"));
		result.append(Discipline.ROOM_NAME);
		result.append(": ");
		result.append(d.getRoom());
		result.append(System.getProperty("line.separator"));
		result.append(Discipline.TIME_NAME);
		result.append(": ");
		result.append(d.getTime());
		result.append(System.getProperty("line.separator"));
		result.append(Discipline.COMMENTARY_NAME);
		result.append(": ");
		result.append(d.getCommentary());
		result.append(System.getProperty("line.separator"));
		result.append(System.getProperty("line.separator"));
		result.append("---------------------------------------------------------");
		result.append(System.getProperty("line.separator"));

		return result.toString();
	}
	
	private String getCommentaryByCode(String code) {
		StringBuilder result = new StringBuilder();
		Discipline d = new Discipline();
		result.append(System.getProperty("line.separator"));

		d = getDisciplineByCode(code);
		if (d == null) {
			return "Disciplina n�o encontrada";
		}
		result.append(Discipline.COMMENTARY_NAME);
		result.append(": ");
		result.append(d.getCommentary());
		result.append(System.getProperty("line.separator"));

		return result.toString();
	}
	
	private Boolean authenticate(String user, String pass) {
		InputStream inputStream = this.getClass().getResourceAsStream(USERS);
		BufferedReader usersFile = new BufferedReader(new InputStreamReader(inputStream));
		String line = null;
		int from = 0, to = 0;
		
		try {
			while ((line = usersFile.readLine()) != null) {
				to = line.indexOf("|");
				if (user.compareTo(line.substring(0, to)) == 0) {
					from = to + 1;
					to = line.indexOf("|", from);
					if (pass.compareTo(line.substring(from, to)) == 0) {
						from = to + 1;
						if (Integer.valueOf(line.substring(from))
								.compareTo(PROFESSOR_AUTH) == 0) {
							return Boolean.TRUE;
						} else {
							return Boolean.FALSE;
						}
					}
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
			return Boolean.FALSE;
		}
		return Boolean.FALSE;
		
	}
	
	private boolean saveDiscipline(Discipline d) {
		BufferedWriter out;
		try {
			FileWriter fw = new FileWriter(DB, true);
			out = new BufferedWriter(fw);
			out.write(d.toString());
			out.newLine();
			out.close();
			return true;
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
	}
	
	private boolean removeDiscipline(String code){
		File tempFile;
		String temp;
		Discipline d = new Discipline();
		try {
			tempFile = File.createTempFile("buffer", ".tmp");
			FileWriter fw = new FileWriter(tempFile);
			BufferedWriter bw = new BufferedWriter(fw);
			
			Reader fr = new FileReader(DB);
			BufferedReader br = new BufferedReader(fr);
			
			while ((temp = br.readLine()) != null) {
				d.createDisciplineFromString(temp);
				if (d.getRemoved() == Boolean.FALSE) {
					// Nao esta removido
					if (code.compareTo(d.getCode()) != 0) {
						// Eh a disciplina que tem que remover
						bw.write(temp);
						bw.newLine();
					}
				}
			}
			bw.close();
			br.close();
			tempFile.renameTo(new File(DB));
			return true;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return false;
	}

	 private void saveTimes(long time){
	    	FileWriter out;
			try {
				out = new FileWriter("times.txt", true);
				out.write(time + "\n");
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
	    }
	
	private String changeCommentaryByCode(String code, String commentary,
			String user, String pass) {
		
		Discipline d = null;
		
		if (authenticate(user, pass).compareTo(Boolean.FALSE) == 0) {
			return "A��o permitida somente a professores.";
		}
		
		d = getDisciplineByCode(code);
		if (d == null) {
			return "Disciplina inv�lida";
		}
		d.setCommentary(commentary);
		if (!removeDiscipline(code) || !saveDiscipline(d)) {
			return "Ocorreu um erro ao salvar a disciplina, tente novamente mais tarde";
		}
		
		return "Opera��o realizada com sucesso";
		
	}
	
}
